<?php
class ViajesModel extends CustomModel
{

    public function getViajes($pageNumber, $status = STATUS_PENDING)
    {
        $viajesAbm = new ABM('viajes');
        $joins = array(
            'conductores' => array('viajes.fkconductor' => 'conductores.idconductor'),
            'rutas'       => array('viajes.fkruta' => 'rutas.idruta'),
            'vehiculos'   => array('viajes.fkvehiculo' => 'vehiculos.idvehiculo'),
            'grupos'      => array('viajes.fkgrupo' => 'grupos.idgrupo'),
        );
        return $viajesAbm->getPaginatedWithJoin($pageNumber, $filter = array('status' => array($status)),$joins, 20, 'salida_timestamp DESC', true);
    }

    public function getViaje($idViaje)
    {
        $viajesAbm = new ABM('viajes');
        return $viajesAbm->get(array('idviaje' => $idViaje, 'status' => array(STATUS_ONLINE, STATUS_OFFLINE, STATUS_PENDING)));
    }

    public function getVehiculos()
    {
        $abm = new ABM('vehiculos');
        return $abm->get(array('status' => STATUS_ONLINE), array('nombre ASC'));
    }

    public function getGrupos(&$vehiculos)
    {
        $abm = new ABM('grupos');
        $grupos = $abm->get(array('status' => STATUS_ONLINE));
        if ($grupos)
        {
            $return = array();
            $vehiculosPorGrupoAbm = new ABM('vehiculos_por_grupo');
            $vehiculosPorGrupo = $vehiculosPorGrupoAbm->get(array('fkgrupo' => array_keys($grupos)), array('nombre ASC'), false, false);
            if (!empty($vehiculosPorGrupo))
            {
                foreach($vehiculosPorGrupo as $vehiculoPorGrupo)
                {
                    if (isset($vehiculos[$vehiculoPorGrupo['fkvehiculo']]))
                    {
                        if (!isset($return[$vehiculoPorGrupo['fkgrupo']]))
                        {
                            $return[$vehiculoPorGrupo['fkgrupo']] = $grupos[$vehiculoPorGrupo['fkgrupo']];
                        }
                        $return[$vehiculoPorGrupo['fkgrupo']]['vehiculos'][$vehiculoPorGrupo['fkvehiculo']] = $vehiculoPorGrupo['fkvehiculo'];
                        $vehiculos[$vehiculoPorGrupo['fkvehiculo']]['in_group'] = true;
                    }
                }
            }
            return $return;
        }
        else
        {
            return false;
        }
    }

    public function getConductores()
    {
        $abm = new ABM('conductores');
        return $abm->get(array('status' => STATUS_ONLINE), array('nombre ASC'));
    }

    public function getRutas()
    {
        $abm = new ABM('rutas');
        return $abm->get(array('status' => STATUS_ONLINE), array('nombre_ruta ASC'));
    }

    public function viajePosible($fkConductor, $fkVehiculo, $fkRuta, $salidaTs, &$viajesEnLaFecha)
    {
        if ($duracionViaje = $this->duracionRutaSegunHorario($fkRuta, $salidaTs))
        {
            $llegadaTs = $salidaTs + $duracionViaje;
            $viajesEnLaFecha = $this->getViajesEnFechaPorVehiculoOConductor($fkConductor, $fkVehiculo, $salidaTs, $llegadaTs);
            if (empty($viajesEnLaFecha))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    public function duracionRutaSegunHorario($fkRuta, $salidaTs)
    {
        $horarioSalida = $salidaTs - gmmktime(0,0,0,date('m', $salidaTs),date('d', $salidaTs),date('Y', $salidaTs));
        // ABM & GET
        $puntosABM = new ABM('puntos_por_ruta');
        $puntosFranjaABM = new ABM('tiempo_por_franja_por_punto');
        $puntos = $puntosABM->get(array('fkruta' => $fkRuta), 'orden ASC');
        $join = array(
            'franjas' => array('tiempo_por_franja_por_punto.fkfranja' => 'franjas.idfranja')
        );
        $puntosPorFranjaRaw = $puntosFranjaABM->getWithJoin(array('fkruta' => $fkRuta), $join, false, false, false);
        // Armar puntos por franja
        $puntosPorFranja = array();
        if (!empty($puntosPorFranjaRaw))
        {
            foreach ($puntosPorFranjaRaw as $puntoPorFranja)
            {
                if (!isset($puntosPorFranja[$puntoPorFranja['fkpunto_por_ruta']]))
                {
                    $puntosPorFranja[$puntoPorFranja['fkpunto_por_ruta']] = array();
                }
                $puntosPorFranja[$puntoPorFranja['fkpunto_por_ruta']][]=$puntoPorFranja;
            }
        }
        // Calcular duracion total
        $sumaDias = 0;
        if (!empty($puntos))
        {
            $duracionTotal = 0;
            foreach($puntos as $punto)
            {
                $duracionPunto = $punto['segundos_anterior'];
                if (isset($puntosPorFranja[$punto['idpunto_por_ruta']]))
                {
                    foreach ($puntosPorFranja[$punto['idpunto_por_ruta']] as $puntoPorFranja)
                    {
                        $diaSemana = date('N', gmmktime(0,0,0,date('m', $salidaTs), date('d',$salidaTs)+$sumaDias, date('Y',$salidaTs)) + $horarioSalida);
                        switch($diaSemana)
                        {
                            case '1': $bitmap = BITMAP_LUNES; break;
                            case '2': $bitmap = BITMAP_MARTES; break;
                            case '3': $bitmap = BITMAP_MIERCOLES; break;
                            case '4': $bitmap = BITMAP_JUEVES; break;
                            case '5': $bitmap = BITMAP_VIERNES; break;
                            case '6': $bitmap = BITMAP_SABADO; break;
                            case '7': $bitmap = BITMAP_DOMINGO; break;
                        }
                        if (($puntoPorFranja['dias'] & $bitmap) > 0)
                        {
                            if (($puntoPorFranja['horario_desde'] <= $horarioSalida) && ($puntoPorFranja['horario_hasta'] >= $horarioSalida))
                            {
                                $duracionPunto = $puntoPorFranja['segundos_anterior'];
                            }
                        }
                    }
                }
                $duracionTotal += $duracionPunto;
                // Si se paso de 24 horas, volver a cero y sumar un dia al dia de la fecha de salida
                $horarioSalida += $duracionPunto;
                if ($horarioSalida >= (24*60*60))
                {
                    $horarioSalida -= (24*60*60);
                    $sumaDias++;
                }
            }
            return $duracionTotal;
        }
        else
        {
            return false;
        }
    }

    public function getViajesEnFechaPorVehiculoOConductor($fkConductor, $fkVehiculo, $salidaTs, $llegadaTs)
    {
        // Filtros
        $fechaInicioFrom   = new dbFilter('salida_timestamp', '>=', $salidaTs);
        $fechaInicioTo     = new dbFilter('salida_timestamp', '<=', $llegadaTs);
        $fechaInicio       = new dbFilter($fechaInicioFrom, 'AND', $fechaInicioTo);
        $fechaFinFrom      = new dbFilter('llegada_estimada_timestamp', '>=', $salidaTs);
        $fechaFinTo        = new dbFilter('llegada_estimada_timestamp', '<=', $llegadaTs);
        $fechaFin          = new dbFilter($fechaFinFrom, 'AND', $fechaFinTo);
        $fechas            = new dbFilter($fechaInicio, 'OR', $fechaFin);
        $conductor         = new dbFilter('fkconductor', '=', $fkConductor);
        $vehiculo          = new dbFilter('fkvehiculo', '=', $fkVehiculo);
        $conductorVehiculo = new dbFilter($conductor, 'OR', $vehiculo);
        $filter            = new dbFilter($conductorVehiculo, 'AND', $fechas);
        $statusA           = new dbFilter('status', '<>', STATUS_OFFLINE);
        $statusB           = new dbFilter('status', '<>', STATUS_HIDDEN);
        $status            = new dbFilter($statusA, 'AND', $statusB);
        $filter            = new dbFilter($filter, 'AND', $status);
        // Select
        $viajes = $this->db->select('*')->from('viajes')->where($filter)->get();
        return $viajes;
    }

    public function insertarViaje($viaje)
    {
        if ($duracionViaje = $this->duracionRutaSegunHorario($viaje['fkruta'], $viaje['salida']))
        {
            $viaje['salida_timestamp'] = $viaje['salida'];
            $viaje['llegada_estimada_timestamp'] = $viaje['salida'] + $duracionViaje;
            $viaje['status'] = STATUS_PENDING;
            $viajesAbm = new ABM('viajes');
            return $viajesAbm->insert($viaje);
        }
        else
        {
            return false;
        }
    }

    public function programarViajes($viajes)
    {
        if (!empty($viajes['programados']))
        {
            $this->db->beginTransaction();
            $viajesAbm = new ABM('viajes');
            foreach ($viajes['programados'] as $programado)
            {
                $insertar = array(
                    'nombre' => $viajes['nombre'] . ' - ' .$programado['salida'],
                    'fkvehiculo' => $viajes['fkvehiculo'],
                    'fkgrupo' => $viajes['fkgrupo'],
                    'fkconductor' => $viajes['fkconductor'],
                    'fkruta' => $viajes['fkruta'],
                    'salida_timestamp' => $programado['salida_timestamp'],
                    'llegada_estimada_timestamp' => $programado['llegada_estimada_timestamp'],
                    'status' => STATUS_PENDING,
                );
                if ($viajesAbm->insert($insertar))
                {

                }
                else
                {
                    $this->db->rollBackTransaction();
                    return false;
                }
            }
            $this->db->commitTransaction();
            return true;
        }
        else
        {
            return false;
        }
    }

    public function borrarViaje($idViaje)
    {
        $viajesAbm = new ABM('viajes');
        return $viajesAbm->update(array('idviaje' => $idViaje), array('status' => STATUS_HIDDEN));
    }

}
?>